#ifndef __G_CRYPT_H__
#define __G_CRYPT_H__

/* Crypt memory map */

#define SM4_BASEADDR                0x000F5200UL
#define RSA_BASEADDR                0x000F5800UL
#define DES_BASEADDR                0x000F8000UL
#define CRC_BASEADDR                0x000F8200UL
#define AES_BASEADDR                0x000F8300UL
#define SHA_BASEADDR                0x000F8600UL

/*******************************  SHA Mode  ***********************************/
#define SHA_DATA(x)         *(volatile int*)(SHA_BASEADDR + 0x00 + x*4)
#define SHA_BDATA(x)        *(volatile uint8_t*)(SHA_BASEADDR + 0x00 + x)
#define SHA_RESULT(x)       *(volatile int*)(SHA_BASEADDR + 0x80 + x*4)
#define SHA_CTRL            *(volatile int*)(SHA_BASEADDR + 0xc0)

/*******************************  AES Mode  ***********************************/
#define AES_CNTRL_REG       *((volatile uint32_t *)(AES_BASEADDR))
#define AES_DATA_REG0       ((volatile uint32_t *)(AES_BASEADDR + 0x10))
#define AES_DATA_REG1       ((volatile uint32_t *)(AES_BASEADDR + 0x14))
#define AES_DATA_REG2       ((volatile uint32_t *)(AES_BASEADDR + 0x18))
#define AES_DATA_REG3       ((volatile uint32_t *)(AES_BASEADDR + 0x1C))
#define AES_KEY_REG0        ((volatile uint32_t *)(AES_BASEADDR + 0x20))
#define AES_KEY_REG1        ((volatile uint32_t *)(AES_BASEADDR + 0x24))
#define AES_KEY_REG2        ((volatile uint32_t *)(AES_BASEADDR + 0x28))
#define AES_KEY_REG3        ((volatile uint32_t *)(AES_BASEADDR + 0x2C))
#define AES_KEY_REG4        ((volatile uint32_t *)(AES_BASEADDR + 0x30))
#define AES_KEY_REG5        ((volatile uint32_t *)(AES_BASEADDR + 0x34))
#define AES_KEY_REG6        ((volatile uint32_t *)(AES_BASEADDR + 0x38))
#define AES_KEY_REG7        ((volatile uint32_t *)(AES_BASEADDR + 0x3C))
#define AES_RAND_REG0       ((volatile uint32_t *)(AES_BASEADDR + 0x40))
#define AES_RAND_REG1       ((volatile uint32_t *)(AES_BASEADDR + 0x44))
#define AES_FKEY_REG0       ((volatile uint32_t *)(AES_BASEADDR + 0x50))
#define AES_DATAB(x)        *(volatile byte*)(AES_BASEADDR + 0x10 + (x))
#define AES_KEYB(x)         *(volatile byte*)(AES_BASEADDR + 0x20 + (x))

/*******************************  DES Mode  ***********************************/
#define DESCNTRL_REG      *((volatile uint32_t *)(DES_BASEADDR+0x00))
#define DESRAND_REG        ((volatile uint32_t *)(DES_BASEADDR+0x0c))
#define DESFAKE_KEY        ((volatile uint32_t *)(DES_BASEADDR+0x10))
#define DESIV_REG          ((volatile uint32_t *)(DES_BASEADDR+0x18))
#define DESDATA_REG        ((volatile uint32_t *)(DES_BASEADDR+0x20))
#define DESKEY1_REG        ((volatile uint32_t *)(DES_BASEADDR+0x28))
#define DESKEY2_REG        ((volatile uint32_t *)(DES_BASEADDR+0x30))
#define DESKEY3_REG        ((volatile uint32_t *)(DES_BASEADDR+0x38))
#define DES_KEYB(x)       *(volatile byte *)(DES_BASEADDR+0x28 + x)
#define DES_DATAB(x)      *(volatile byte *)(DES_BASEADDR+0x20 + x)

/*******************************  SM4 Mode  ***********************************/
#define SM4_REG0         (*(volatile uint32_t *)(SM4_BASEADDR + 0x0))
#define SM4_REG1         (*(volatile uint32_t *)(SM4_BASEADDR + 0x4))
#define SM4_IER          (*(volatile uint32_t *)(SM4_BASEADDR + 0x8))
#define SM4_MR           (*(volatile uint32_t *)(SM4_BASEADDR + 0xc))
#define SM4_KEY0         ((volatile uint32_t *)(SM4_BASEADDR + 0x10))
#define SM4_KEY1         ((volatile uint32_t *)(SM4_BASEADDR + 0x14))
#define SM4_KEY2         ((volatile uint32_t *)(SM4_BASEADDR + 0x18))
#define SM4_KEY3         ((volatile uint32_t *)(SM4_BASEADDR + 0x1c))
#define SM4_IV0          ((volatile uint32_t *)(SM4_BASEADDR + 0x20))
#define SM4_IV1          ((volatile uint32_t *)(SM4_BASEADDR + 0x24))
#define SM4_IV2          ((volatile uint32_t *)(SM4_BASEADDR + 0x28))
#define SM4_IV3          ((volatile uint32_t *)(SM4_BASEADDR + 0x2c))
#define SM4_DATA0        ((volatile uint32_t *)(SM4_BASEADDR + 0x30))
#define SM4_DATA1        ((volatile uint32_t *)(SM4_BASEADDR + 0x34))
#define SM4_DATA2        ((volatile uint32_t *)(SM4_BASEADDR + 0x38))
#define SM4_DATA3        ((volatile uint32_t *)(SM4_BASEADDR + 0x3c))

/*******************************  RSA Mode  ***********************************/
#define RECR             (*((volatile uint32_t *)(RSA_BASEADDR+0x00)))
#define RESR             (*((volatile uint32_t *)(RSA_BASEADDR+0x04)))
#define REFR             (*((volatile uint32_t *)(RSA_BASEADDR+0x08)))
#define RESCR            (*((volatile uint32_t *)(RSA_BASEADDR+0x0c)))
#define REDQR            (*((volatile uint32_t *)(RSA_BASEADDR+0x10)))
#define REINT            (*((volatile uint32_t *)(RSA_BASEADDR+0x14)))
#define RECFR            (*((volatile uint32_t *)(RSA_BASEADDR+0x18)))
#define REBKR            ((volatile uint32_t *)(RSA_BASEADDR+0x1c))
#define REDRR            (*((volatile uint32_t *)(RSA_BASEADDR+0x24)))

#define REDAR            ((volatile uint32_t *)(RSA_BASEADDR+0x100))
#define REDAR1           ((volatile uint32_t *)(RSA_BASEADDR+0x120))
#define REDAR2           ((volatile uint32_t *)(RSA_BASEADDR+0x140))
#define REDAR3           ((volatile uint32_t *)(RSA_BASEADDR+0x160))
#define REDXR            ((volatile uint32_t *)(RSA_BASEADDR+0x200))
#define REDXR1           ((volatile uint32_t *)(RSA_BASEADDR+0x220))
#define REDXR2           ((volatile uint32_t *)(RSA_BASEADDR+0x240))
#define REDXR3           ((volatile uint32_t *)(RSA_BASEADDR+0x260))
#define REDYR            ((volatile uint32_t *)(RSA_BASEADDR+0x280))
#define REDYR1           ((volatile uint32_t *)(RSA_BASEADDR+0x2a0))
#define REDYR2           ((volatile uint32_t *)(RSA_BASEADDR+0x2c0))
#define REDYR3           ((volatile uint32_t *)(RSA_BASEADDR+0x2e0))
#define REDBR            ((volatile uint32_t *)(RSA_BASEADDR+0x300))
#define REDBR1           ((volatile uint32_t *)(RSA_BASEADDR+0x320))
#define REDBR2           ((volatile uint32_t *)(RSA_BASEADDR+0x340))
#define REDBR3           ((volatile uint32_t *)(RSA_BASEADDR+0x360))
#define REDBRH           ((volatile uint32_t *)(RSA_BASEADDR+0x380))
#define REDCR            ((volatile uint32_t *)(RSA_BASEADDR+0x500))
#define REDCR1           ((volatile uint32_t *)(RSA_BASEADDR+0x520))
#define REDCR2           ((volatile uint32_t *)(RSA_BASEADDR+0x540))
#define REDCR3           ((volatile uint32_t *)(RSA_BASEADDR+0x560))
#define REDCRH           ((volatile uint32_t *)(RSA_BASEADDR+0x580))
#define REDUR            ((volatile uint32_t *)(RSA_BASEADDR+0x600))
#define REDVR            ((volatile uint32_t *)(RSA_BASEADDR+0x680))
#define REDVR2           ((volatile uint32_t *)(RSA_BASEADDR+0x6c0))
#define REDPR            ((volatile uint32_t *)(RSA_BASEADDR+0x700))
#define REDPR1           ((volatile uint32_t *)(RSA_BASEADDR+0x720))
#define REDPR2           ((volatile uint32_t *)(RSA_BASEADDR+0x740))
#define REDPR3           ((volatile uint32_t *)(RSA_BASEADDR+0x760))
#define REDPRH           ((volatile uint32_t *)(RSA_BASEADDR+0x780))

#define REDAR_4096       ((volatile uint32_t *)(RSA_BASEADDR+0x800))
#define REDBR_4096       ((volatile uint32_t *)(RSA_BASEADDR+0xa00))
#define REDCR_4096       ((volatile uint32_t *)(RSA_BASEADDR+0xc00))
#define REDPR_4096       ((volatile uint32_t *)(RSA_BASEADDR+0xe00))
#define REDXR_4096       ((volatile uint32_t *)(RSA_BASEADDR+0x1000))
#define REDYR_4096       ((volatile uint32_t *)(RSA_BASEADDR+0x1200))
#define REDUR_4096       ((volatile uint32_t *)(RSA_BASEADDR+0x1400))
#define REDVR_4096       ((volatile uint32_t *)(RSA_BASEADDR+0x1600))

#define REDAR_WLEN_VERDICT(wlen)    (wlen <= 128 ? 0 : 1)
#define REDBR_WLEN_VERDICT(wlen)    (wlen <= 64 ? 0 : 1)
#define REDCR_WLEN_VERDICT(wlen)    (wlen <= 128 ? 0 : 1)
#define REDPR_WLEN_VERDICT(wlen)    (wlen <= 64 ? 0 : 1)

#define REDAR_SEL(type)  (type == 0 ? REDAR : REDAR_4096)
#define REDBR_SEL(type)  (type == 0 ? REDBR : REDBR_4096)
#define REDCR_SEL(type)  (type == 0 ? REDCR : REDCR_4096)
#define REDPR_SEL(type)  (type == 0 ? REDPR : REDPR_4096)

// #define REDXR_SEL(type)  (wlen <=32 ? REDXR : REDXR_4096)
// #define REDYR_SEL(type)  (wlen <=32 ? REDYR : REDYR_4096)
// #define REDUR_SEL(type)  (wlen <=32 ? REDUR : REDUR_4096)
// #define REDVR_SEL(type)  (wlen <=32 ? REDVR : REDVR_4096)

/*******************************  CRC Mode  ***********************************/
#define CRC_RESULT_REG     *(volatile uint32_t *)(CRC_BASEADDR+0X04)
#define CRC_MASK_REG       *(volatile uint32_t *)(CRC_BASEADDR+0X08)
#define CRC_DATAB_REG      *(volatile byte *)(CRC_BASEADDR+0X80)
#define CRC_DATAS_REG      *(volatile short int *)(CRC_BASEADDR+0X80)
#define CRC_DATA_REG       *(volatile int *)(CRC_BASEADDR+0X80)

/********************  Bit definition for AES register  ***********************/
#define AES_CNTRL_REG_START         (0x01)
#define AES_CNTRL_KEY_SEL_128       (0X00)
#define AES_CNTRL_KEY_SEL_192       (0X08)
#define AES_CNTRL_KEY_SEL_256       (0X10)
#define AES_CNTRL_ENC               (0X00)
#define AES_CNTRL_DEC               (0X02)
#define AES_CNTRL_ENABLE_RAND       (0X20)

/********************  Bit definition for DES register  ***********************/
#define DESCNTRL_REG_START            (0x01)
#define DESCNTRL_REG_ENCRYPT          (0x02)
#define DESCNTRL_REG_KEY_SEL          (0x0c)
#define DESCNTRL_REG_DES_MODE         (0x10)
#define DESCNTRL_REG_OP_MODE          (0x60)
#define DESCNTRL_REG_RAND_EN          (0x80)

#define DESCNTRL_REG_ENCRYPT_ENC      (0X00)
#define DESCNTRL_REG_ENCRYPT_DEC      (0X02)

#define DESCNTRL_REG_KEY_SEL_DES1     (0x00)
#define DESCNTRL_REG_KEY_SEL_DES2     (0x04)
#define DESCNTRL_REG_KEY_SEL_DES3     (0x08)

#define DESCNTRL_REG_KEY_SEL_TDES2    (0x00)
#define DESCNTRL_REG_KEY_SEL_TDES3    (0x04)

#define DESCNTRL_REG_DES_MODE_DES     (0X00)
#define DESCNTRL_REG_DES_MODE_TDES    (0X10)

#define DESCNTRL_REG_OP_MODE_ECB      (0x00)
#define DESCNTRL_REG_OP_MODE_CBC      (0x20)

/********************  Bit definition for RSA register  ***********************/
//sfr bit
// RECR register
#define RECR_start                    (0x01)
#define RECR_idle_run                 (0x02)
#define RECR_bus_crypt_en             (0x04)
// RESR register
#define RESR_error_flag               (0x01)
#define RESR_opdata_error             (0x02)
//REINT register
#define REINT_rsa_int                 (0x01)

/********************  Bit definition for SM4 register  ***********************/
#define SM4_CNTRL_ECB (0X00)
#define SM4_CNTRL_CBC (0X02)
#define SM4_CNTRL_ENC (0X01)
#define SM4_CNTRL_DEC (0X00)

#define CMPERR          (('C'<<24)|('M'<<16)|('P'<<8)|('E'))
#define EQUAL           (('E'<<24)|('Q'<<16)|('U'<<8)|('A'))
#define UNEQUAL         (('U'<<24)|('E'<<16)|('Q'<<8)|('U'))
#define BIGGER          (('B'<<24)|('I'<<16)|('G'<<8)|('G'))
#define SMALLER         (('S'<<24)|('M'<<16)|('A'<<8)|('L'))

typedef enum
{
    ECB = (('P'<<24)|('E'<<16)|('C'<<8)|('B')),
    CBC = (('P'<<24)|('C'<<16)|('B'<<8)|('C'))
}G_PACK_ModeTypeDef;

typedef enum
{
    ENC = (('C'<<24)|('E'<<16)|('N'<<8)|('C')),
    DEC = (('C'<<24)|('D'<<16)|('E'<<8)|('C'))
}G_CRYPT_ModeTypeDef;

typedef uint32_t (*rng_callback)(void *rand, uint32_t size, void *p_rng);

void G_CRYPT_Reset(void);
void G_CRYPT_ITClear(void);
void G_CRYPT_Data_Rand(rng_callback f_rng, void *p_rng);


#endif
